﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling;
using System.Diagnostics;

namespace DSLFactory.VSCTDesigner
{
    /// <summary>
    /// 
    /// </summary>
    [RuleOn(typeof(Command), FireTime = TimeToFire.TopLevelCommit)]
    class CommandGuidDeleteRule : DeleteRule 
    {
        /// <summary>
        /// Alerts listeners that an element has been deleted from the model.
        /// </summary>
        /// <param name="e">Provides data for the ElementDeleted event.</param>
        public override void ElementDeleted(ElementDeletedEventArgs e)
        {
            Command cmd = e.ModelElement as Command;

            if( e.ModelElement is ExternCommand )
                return;

            if( e.ModelElement.Store.InUndoRedoOrRollback )
                return;

            // Suppression de son id 
            GuidSymbolHelper.RemoveIDSymbol(cmd.CommandTable, cmd.Guid, cmd.ID);
            // Suppression du idlist
            if( cmd is Combo )
            {
                GuidSymbolHelper.RemoveIDSymbol(cmd.CommandTable, cmd.Guid, ((Combo)cmd).IdCommandList);
            }

            // Si le guid ne contient plus rien, on le supprime
            var guid = cmd.CommandTable.Symbols.FirstOrDefault(g=>g.Name==cmd.Guid);
            if( guid != null && guid.IDSymbols.Count==0 )
                GuidSymbolHelper.RemoveGuidSymbol(cmd.CommandTable, cmd.Guid);            
        }
    }

    [RuleOn(typeof(Command), FireTime=TimeToFire.LocalCommit)]
    [RuleOn(typeof(Bitmap), FireTime = TimeToFire.LocalCommit)]
    class CommandIDChangeRule : ChangeRule
    {
        /// <summary>
        /// Lors d'un chagement de guid, on s'assure que les symboles restent synchronisés
        /// </summary>
        /// <param name="e"></param>
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            if( e.ModelElement is ExternCommand )
                return;

            if( e.ModelElement.Store.InUndoRedoOrRollback || e.ModelElement.Store.TransactionManager.CurrentTransaction.TopLevelTransaction.IsSerializing )
                return;

            if( e.DomainProperty.Id == Command.GuidDomainPropertyId )
            {
                string value = (string)e.NewValue;
                Command cmd = e.ModelElement as Command;
                CommandTable ct = cmd.CommandTable;
                GuidSymbol guid = GuidSymbolHelper.EnsureGuidSymbol(ct, value);
                // Au cas ou le guid a été défini après l'ID
                GuidSymbolHelper.EnsureIDSymbol(ct, guid, cmd.ID);
            }

            // Création dans la table des symboles du nouveau id si il existe pas
            if( e.DomainProperty.Id == Command.IDDomainPropertyId || e.DomainProperty.Id == Combo.IdCommandListDomainPropertyId )
            {
                string value = (string)e.NewValue;
                string oldValue = (string)e.OldValue;
                Command cmd = e.ModelElement as Command;
                CommandTable ct = cmd.CommandTable;
                GuidSymbol guid = GetGuidSymbol(ct, cmd, cmd.Guid);
                if( guid == null )
                    return; // On attend que le guid soit défini

                GuidSymbolHelper.EnsureIDSymbol(ct, guid, value);
                // On va supprimer l'ancien id
                GuidSymbolHelper.RemoveIDSymbol(guid, oldValue);
            }
        }

        /// <summary>
        /// Gets the GUID symbol.
        /// </summary>
        /// <param name="cmd">The CMD.</param>
        /// <param name="guidName">Name of the GUID.</param>
        /// <returns></returns>
        private GuidSymbol GetGuidSymbol(CommandTable ct, Command cmd, string guidName)
        {
            if( cmd == null || String.IsNullOrEmpty(guidName) )
                return null;

            return GuidSymbolHelper.EnsureGuidSymbol(ct, guidName);
        }
    }
}
